package persistent.prestige.console.task.w04;

import java.nio.ByteBuffer;
import java.util.TreeSet;
import java.util.concurrent.locks.ReentrantLock;


/**
 * 
 * 简易版本的多线程直接内存池
 * 该线程池的实现纬度为一纬的，  也就是 ByteBuffer 与 其占用的内存 一起放入到对象池中。
 * 师尊在课程中其实也提到过，ByteBuffer 在堆中有代表，，对外内存其实另外一块内存，如果从这两个维度分别设计内存，就更好。
 * 
 * @author dingwei2
 * 
 *
 */
public class DirectByteBufPool {
	
	
	private static TreeSet<DirectByteBuf> bufPools = new TreeSet<DirectByteBuf>();
	
	private static ReentrantLock mainLock = new ReentrantLock();
	
	private static DirectByteBuf unwap = new DirectByteBuf(0);
	
	public static final int MAX_CACHE_SIZE = 1024 * 1024 * 8;//超过8M的内存，不缓存
	
	
	
	/**
	 * 
	 * @param needCapacity
	 * @return
	 */
	public static final DirectByteBuf get(int needCapacity) {
		
		if(needCapacity < 1 ) {
			throw new RuntimeException(String.format("needCapacity非法,%d", needCapacity));
		}
		
		if(needCapacity >= MAX_CACHE_SIZE) {
			return new DirectByteBuf(ByteBuffer.allocateDirect(needCapacity), false);
		}
		
		DirectByteBuf buf = null;
		mainLock.lock();
		try {
			unwap.setCapacity(needCapacity);
			buf = bufPools.higher(unwap);
			if(buf != null) {
				bufPools.remove(buf);
				return buf;
			} //这里主要是对象池中获取一个
			
		} finally {
			mainLock.unlock();
		}
		
		//如果对象池中没有可用内存，则创建一个
		buf = new DirectByteBuf(ByteBuffer.allocateDirect(needCapacity), true);
		return buf;
		
		
	}
	
	public static final void realse(DirectByteBuf buf) {
		if(buf == null) return;
		if(buf.isCache()) {
			buf.unwap().clear(); //恢复相关指针，待下次写人
			
			mainLock.lock();
			try {
				bufPools.add(buf);
			} finally {
				mainLock.unlock();
			}
			
		} else {
			buf = null;//help GC
		}
	}

}
